package com.siyoumi.app.modules.app_book.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.siyoumi.app.entity.*;
import com.siyoumi.app.modules.app_book.vo.*;
import com.siyoumi.app.service.*;
import com.siyoumi.component.XApp;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XSpringContext;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.service.IWebService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XJson;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

//
@Slf4j
@Service
public class SvcBookSpu
        implements IWebService {
    static public SvcBookSpu getBean() {
        return XSpringContext.getBean(SvcBookSpu.class);
    }

    static public BookSpuService getApp() {
        return BookSpuService.getBean();
    }

    public List<Map<String, Object>> getList(String storeId) {
        JoinWrapperPlus<BookSpu> query = listQuery();
        query.eq("bspu_store_id", storeId);
        query.select("bspu_id", "bspu_name");
        return getApp().getMaps(query);
    }

    public List<Map<String, Object>> apiSpuList(InputData inputData) {
        //房源列表
        String[] select = {
                "bspu_id",
                "bspu_name",
                "bspu_store_id",
                "bspu_logo",
                "bspu_user_count",
                "bspu_area",
        };
        JoinWrapperPlus<BookSpu> query = SvcBookSpu.getBean().listQuery(inputData);
        query.eq("bspu_enable", 1);
        query.select(select);

        IPage<BookSpu> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), false);

        IPage<Map<String, Object>> pageData = SvcBookSpu.getApp().getMaps(page, query);

        List<Map<String, Object>> listSpu = pageData.getRecords();
        List<String> spuIds = listSpu.stream().map(item -> (String) item.get("bspu_id")).collect(Collectors.toList());
        List<Map<String, Object>> listSku = new ArrayList<>(); //所有房间的sku
        if (!spuIds.isEmpty()) {
            listSku = SvcBookSku.getBean().getList(spuIds);
        }

        for (Map<String, Object> item : listSpu) {
            BookSpu entitySpu = XBean.fromMap(item, BookSpu.class);
            //sku
            List<Map<String, Object>> listSpuSku = listSku.stream()
                    .filter(i -> i.get("bsku_spu_id").equals(entitySpu.getKey()))
                    .collect(Collectors.toList());
            item.put("list_sku", listSpuSku);
        }

        return listSpu;
    }

    public XReturn validCommon(BookSpu entity) {
        if (entity == null) {
            return EnumSys.ERR_VAL.getR("spu_id异常");
        }
        if (entity.getBspu_del() != 0) {
            return EnumSys.ERR_VAL.getR("房源不存在");
        }
        return EnumSys.OK.getR();
    }

    /**
     * 是否有效
     *
     * @param entity
     */
    public XReturn valid(BookSpu entity) {
        XReturn r = validCommon(entity);
        if (r.err()) {
            return r;
        }

        if (!entity.enable()) {
            return EnumSys.ERR_VAL.getR("房源已下架");
        }
        return EnumSys.OK.getR();
    }

    /**
     * 能否编辑
     *
     * @param entity
     */
    public XReturn canEdit(BookSpu entity) {
        XReturn r = validCommon(entity);
        if (r.err()) {
            return r;
        }

        if (entity.enable()) {
            return EnumSys.ERR_VAL.getR("房源已上架，无法操作");
        }

        return EnumSys.OK.getR();
    }

    public JoinWrapperPlus<BookSpu> listQuery(String storeId) {
        JoinWrapperPlus<BookSpu> query = listQuery();
        query.eq("bspu_store_id", storeId);
        return query;
    }

    public JoinWrapperPlus<BookSpu> listQuery() {
        return listQuery(InputData.getIns());
    }

    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<BookSpu> listQuery(InputData inputData) {
        String name = inputData.input("name");
        String storeId = inputData.input("store_id");
        String collect = inputData.input("collect");

        JoinWrapperPlus<BookSpu> query = getApp().join();
        query.eq("bspu_x_id", XHttpContext.getX())
                .eq("bspu_del", 0);
        //排序
        query.orderByAsc("bspu_order")
                .orderByDesc("bspu_id");
        if (XStr.hasAnyText(name)) { //名称
            query.like("bspu_name", name);
        }
        if (XStr.hasAnyText(storeId)) { //商家
            query.eq("bspu_store_id", storeId);
        }
        if ("1".equals(collect)) { //收藏列表
            String sqlExists = "SELECT 1 FROM wx_app.t_sys_uv WHERE uv_type = 'spu_collect' AND uv_type_id = bspu_id AND uv_uid = {0}";
            query.exists(sqlExists, getUid());
        }

        return query;
    }

    /**
     * 每日库存
     *
     * @return query
     */
    public JoinWrapperPlus<BookSpuDay> listDayQuery(String spuId) {
        JoinWrapperPlus<BookSpuDay> query = BookSpuDayService.getBean().join();
        query.eq("bspud_x_id", XHttpContext.getX())
                .eq("bspud_spu_id", spuId);

        return query;
    }

    public List<SpuDayData> listDay(BookSpu entitySpu, LocalDateTime dateBegin, LocalDateTime dateEnd) {
        List<BookSpuDay> listDay = listDay(entitySpu.getKey(), dateBegin, dateEnd);
        List<LocalDateTime> dates = XDate.getDateList(dateBegin, dateEnd, null);
        List<SpuDayData> list = new ArrayList<>();
        for (LocalDateTime date : dates) {
            BookSpuDay entity = listDay.stream().filter(item -> item.getBspud_date().equals(date)).findFirst()
                    .orElse(null);
            if (entity == null) {
                entity = new BookSpuDay();
                entity.setBspud_stock_add(0);
                entity.setBspud_stock_use(0L);
                entity.setBspud_spu_add_price(BigDecimal.ZERO);
            }

            SpuDayData item = new SpuDayData();
            item.setDate(date);
            item.setStock_total(entitySpu.getBspu_stock_max() + entity.getBspud_stock_add());
            item.setLeft_total(entity.leftStock(entitySpu.getBspu_stock_max()));
            item.setAdd_price(entity.getBspud_spu_add_price());
            item.setStock_add(entity.getBspud_stock_add());

            list.add(item);
        }

        return list;
    }

    public List<BookSpuDay> listDay(String spuId, LocalDateTime dateBegin, LocalDateTime dateEnd) {
        String key = spuId + XStr.md5(XDate.toDateString(dateBegin) + XDate.toDateString(dateEnd));
        return XHttpContext.getAndSetData(key, k -> {
            JoinWrapperPlus<BookSpuDay> query = listDayQuery(spuId);
            query.between("bspud_date", dateBegin, dateEnd);

            return BookSpuDayService.getBean().get(query);
        });
    }

    /**
     * 房源套餐
     *
     * @return query
     */
    public JoinWrapperPlus<BookSpuSet> listSetQuery(String spuId) {
        JoinWrapperPlus<BookSpuSet> query = BookSpuSetService.getBean().join();
        query.eq("bset_x_id", XHttpContext.getX())
                .eq("bset_spu_id", spuId);

        return query;
    }

    /**
     * 房源套餐 ids
     *
     * @param spuId
     */
    public List<String> getSpuSetIds(String spuId) {
        JoinWrapperPlus<BookSpuSet> query = listSetQuery(spuId);
        query.select("bset_set_id");
        List<BookSpuSet> list = BookSpuSetService.getBean().get(query);
        return list.stream().map(item -> item.getBset_set_id()).collect(Collectors.toList());
    }

    public XReturn edit(InputData inputData, VaBookSpu vo) {
        List<String> ignoreField = new ArrayList<>();
        if (inputData.isAdminEdit()) {
            //ignoreField.add("bspu_acc_id");
        }

        return XApp.getTransaction().execute(status -> {
            XReturn r = getApp().saveEntity(inputData, vo, true, ignoreField);
            BookSpu entity = r.getData("entity");

            //txt
            BookSpuTxt entityTxt = BookSpuTxtService.getBean().getEntity(entity.getBspu_id());
            BookSpuTxt entityTxtUpdate = new BookSpuTxt();
            if (entityTxt == null) {
                entityTxtUpdate.setBsput_id(entity.getBspu_id());
                entityTxtUpdate.setBsput_x_id(XHttpContext.getX());
                entityTxtUpdate.setBsput_acc_id(entity.getBspu_acc_id());
            }
            XBean.copyProperties(vo, entityTxtUpdate);
            BookSpuTxtService.getBean().saveOrUpdatePassEqualField(entityTxt, entityTxtUpdate);

            if (inputData.isAdminAdd()) {
                //添加操作，预生成sku
                List<Integer> listDay = List.of(1, 3, 14, 30);
                for (Integer day : listDay) {
                    VaBookSku voSku = new VaBookSku();
                    voSku.setBsku_acc_id(entity.getBspu_acc_id());
                    voSku.setBsku_spu_id(entity.getKey());
                    voSku.setBsku_day(day);
                    voSku.setBsku_store_id(entity.getBspu_store_id());
                    voSku.setBsku_day_price(BigDecimal.ZERO);
                    SvcBookSku.getBean().save(inputData, voSku);
                }
            }

            if (vo.getSet_do() == 1) {
                //删除旧套餐
                delSet(entity.getBspu_id());

                //添加新套餐
                List<BookSpuSet> list = new ArrayList<>();
                for (String setId : vo.getSet_ids()) {
                    BookSpuSet entitySet = new BookSpuSet();
                    entitySet.setAutoID();
                    entitySet.setBset_acc_id(entity.getBspu_acc_id());
                    entitySet.setBset_x_id(XHttpContext.getX());
                    entitySet.setBset_set_id(setId);
                    entitySet.setBset_spu_id(entity.getKey());
                    list.add(entitySet);
                }
                BookSpuSetService.getBean().saveBatch(list);
            }

            if (vo.getSet_item_device() == 1) { //房源设备
                SvcBookItem.getBean().updateItemZZ("device", entity.getKey(), vo.getBspu_store_id(), vo.getItem_device_ids());
            }

            return r;
        });
    }


    /**
     * 删除套餐
     *
     * @param spuId
     */
    public XReturn delSet(String spuId) {
        JoinWrapperPlus<BookSpuSet> query = listSetQuery(spuId);
        BookSpuSetService.getBean().remove(query);

        return EnumSys.OK.getR();
    }

    /**
     * 批量减库存
     *
     * @param vo
     */
    public XReturn dayBatchUpdateStock(VaBookSpuDayUpdateStock vo) {
        BookSpu entitySpu = getApp().getEntityLock(vo.getSpu_id());
        XValidator.err(validCommon(entitySpu));

        //日期更新库存和加价
        BookSpuDayService.getBean().update()
                .set("bspud_stock_use_add", vo.getStock_add_use())
                .eq("bspud_spu_id", entitySpu.getKey())
                .between("bspud_date", vo.getBegin_date(), vo.getEnd_date())
                .update();

        return EnumSys.OK.getR();
    }

    /**
     * 批量修改日期库存
     *
     * @param vo
     */
    public XReturn dayEditBatch(VaBookSpuDay vo) {
        BookSpu entitySpu = getApp().getEntityLock(vo.getBspud_spu_id());
        XValidator.err(validCommon(entitySpu));

        //日期更新库存和加价
        List<LocalDateTime> dateList = XDate.getDateList(vo.getBegin_date(), vo.getEnd_date(), vo.getWeek());
        List<BookSpuDay> listSpuDay = listDay(vo.getBspud_spu_id(), vo.getBegin_date(), vo.getEnd_date());
        for (LocalDateTime date : dateList) {
            BookSpuDay entity = listSpuDay.stream().filter(item -> item.getBspud_date().equals(date)).findFirst().orElse(null);

            BookSpuDay entityUpdate = new BookSpuDay();
            if (entity == null) {
                entityUpdate.setAutoID();
                entityUpdate.setBspud_spu_id(entitySpu.getKey());
                entityUpdate.setBspud_x_id(entitySpu.getBspu_x_id());
                entityUpdate.setBspud_date(date);
            }
            entityUpdate.setBspud_spu_add_price(vo.getBspud_spu_add_price());
            entityUpdate.setBspud_stock_add(vo.getBspud_stock_add());
            BookSpuDayService.getBean().saveOrUpdatePassEqualField(entity, entityUpdate);
        }

        return EnumSys.OK.getR();
    }

    /**
     * 删除
     */
    @SneakyThrows
    @Transactional(propagation = Propagation.MANDATORY)
    public XReturn delete(List<String> ids) {
        XReturn r = XReturn.getR(0);

        JoinWrapperPlus<BookSpu> query = listQuery();
        query.in(BookSpu.tableKey(), ids);
        List<BookSpu> listSpu = getApp().get(query);
        for (BookSpu entity : listSpu) {
            if (entity.getBspu_enable() == 1) {
                return XReturn.getR(20108, entity.getBspu_name() + "已上架不能删除");
            }
        }

        getApp().delete(ids);

        return r;
    }


    /**
     * 审核
     *
     * @param vo
     */
    @Transactional(rollbackFor = Exception.class)
    public XReturn audit(VoBookSpuAudit vo) {
        List<BookSpu> list = getApp().get(vo.getIds());
        if (list.isEmpty()) {
            return EnumSys.OK.getR();
        }

        for (BookSpu entity : list) {
            if (Objects.equals(entity.getBspu_enable(), vo.getEnable())) {
                continue;
            }
            if (vo.getEnable() == 1) {
                JoinWrapperPlus<BookSku> query = SvcBookSku.getBean().listQuery(entity.getBspu_id());
                query.eq("bsku_enable", 1);
                Long skuCount = SvcBookSku.getApp().count(query);
                if (skuCount <= 0) {
                    XValidator.err(EnumSys.ENV_ERR.getR(entity.getBspu_name() + "：请上架价格"));
                }
            }

            BookSpu entityUpdate = new BookSpu();
            entityUpdate.setBspu_id(entity.getKey());
            entityUpdate.setBspu_enable(vo.getEnable());
            entityUpdate.setBspu_enable_date(XDate.now());
            getApp().updateById(entityUpdate);
        }

        SvcBookStore.getBean().updateDay1Price(list.get(0).getBspu_store_id());
        return EnumSys.OK.getR();
    }
}
